package com.tony.fileserver.controller;

import com.tony.fileserver.service.FileServerService;
import com.tony.fileserver.transferobject.FileDTO;
import com.tony.fileserver.util.MD5Util;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * 文件处理接口类
 */
@Api("文件处理类")
@CrossOrigin(origins = "*", maxAge = 3600)  // 允许所有域名访问
@RestController
@RequestMapping("/file")
public class FileServerController {
    private static Logger logger = LoggerFactory.getLogger(FileServerController.class);

    @Autowired
    @Qualifier("fileService")
    FileServerService fileService;

    @Value("${server.address}")
    private String serverAddress;

    @Value("${server.port}")
    private String serverPort;

    /**
     * 上传文件
     *
     * @param file               文件信息
     * @param redirectAttributes
     * @return
     */
    @ApiOperation("")
    @PostMapping("/")
    public String fileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
        try {
            FileDTO fileDTO = new FileDTO(file.getOriginalFilename(), file.getContentType(), file.getSize(),
                    MD5Util.getMD5(file.getInputStream()), file.getBytes());

            fileService.saveFile(fileDTO);
        } catch (IOException | NoSuchAlgorithmException e) {
            logger.error("文件上传异常，异常信息：" + e.getMessage(), e);

            redirectAttributes.addFlashAttribute("message",
                    "Your " + file.getOriginalFilename() + " is wrong!");
            return "redirect:/";
        }

        redirectAttributes.addFlashAttribute("message",
                "You successfully uploaded " + file.getOriginalFilename() + "!");

        return "redirect:/";
    }

    @PostMapping("/upload")
    @ResponseBody
    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
        try {
            FileDTO f = new FileDTO(file.getOriginalFilename(), file.getContentType(), file.getSize(),
                    MD5Util.getMD5(file.getInputStream()), file.getBytes());
            FileDTO returnFile = fileService.saveFile(f);
            String path = "//" + serverAddress + ":" + serverPort + "/view/" + returnFile.getId();
            return ResponseEntity.status(HttpStatus.OK).body(path);

        } catch (IOException | NoSuchAlgorithmException e) {
            logger.error("文件上次异常，异常信息： " + e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

    /**
     * 获取文件片信息
     *
     * @param id
     * @return
     */
    @GetMapping("download/{id}")
    @ResponseBody
    public ResponseEntity<Object> serveFile(@PathVariable String id) {

        FileDTO file = fileService.getFileById(id);

        if (file != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=\"" + file.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
                    .header(HttpHeaders.CONTENT_LENGTH, file.getSize() + "")
                    .header("Connection", "close")
                    .body((Object) file.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body((Object) "File was not fount");
        }
    }

    /**
     * 在线显示文件
     *
     * @param id
     * @return
     */
    @GetMapping("/view/{id}")
    @ResponseBody
    public ResponseEntity<Object> serveFileOnline(@PathVariable String id) {

        FileDTO file = fileService.getFileById(id);

        if (file != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\"" + file.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, file.getContentType())
                    .header(HttpHeaders.CONTENT_LENGTH, file.getSize() + "")
                    .header("Connection", "close")
                    .body((Object) file.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body((Object) "File was not fount");
        }
    }

    /**
     * 分页查询文件
     * @param pageIndex 页码
     * @param pageSize 分页大小
     * @return 文件列表
     */
    @GetMapping("files/{pageIndex}/{pageSize}")
    @ResponseBody
    public List<FileDTO> listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize){
        return fileService.listFiles(pageIndex, pageSize);
    }

    /**
     * 分页查询文件
     * @param pageIndex 页码
     * @param pageSize 分页大小
     * @param desc 是否是按照上传时间降序排序
     * @return 文件列表
     */
    @GetMapping("files/{pageIndex}/{pageSize}/{desc}")
    @ResponseBody
    public List<FileDTO> listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize, @PathVariable boolean desc){
        return fileService.listFiles(pageIndex, pageSize, desc);
    }

    /**
     * 获取文件大小
     * @return
     */
    @GetMapping("count")
    public long countFiles(){
        return fileService.countFiles();
    }

    /**
     * 删除文件
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    @ResponseBody
    public ResponseEntity<String> deleteFile(@PathVariable String id) {
        try {
            fileService.removeFile(id);
            return ResponseEntity.status(HttpStatus.OK).body("DELETE Success!");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }
}
